
/**
 * sketch_robot_sliders
 *
 * used in combination with the arduino sketch:
 * 
 * sketch_servo_and_serial_com
 * 
 * 2008, James Stone, http://www.manofstone.com
 *
 * derived from Scrollbar. 
 * 
 * Move the scrollbars left and right to change the positions of the images. 
 *
 * Each scrollbar send serial data to the arduino in the following format
 * "sxyyyy" where s is the char 's', x is the servo #, 0 - 7, and y is the 4 digit
 * amount to set the servo to, from 0500 - 5500
 * note: extreme ranges can result in servo damage, start at 3000 and then
 * experiment
 *
 */
 
import processing.serial.*;



// change for your serial port used by the arduino, the one starting with tty.
// String portname = "/dev/tty.usbserial-A5002rKW"; // james arduino
 String portname = "/dev/tty.usbserial-A1001NQr"; // thomas' arduino, w/ feet
//String portname = "/dev/tty.SerialPort-1"; // for testing
Serial port;  // Create object from Serial class

HScrollbar hs1, hs2, hs3, hs4, hs5, hs6;

long sDelay = 50; // how long between updates
long lastSerial = 0; // last time serial was sent
int sCount = 0;

void setup()
{
  size(500, 350);
  noStroke();

  // init scrollbars
  hs1 = new HScrollbar(0, 50, width, 10, 3*5+1);
  hs1.servo = 0;
  hs2 = new HScrollbar(0, 100, width, 10, 3*5+1);
  hs2.servo = 1;
  hs3 = new HScrollbar(0, 150, width, 10, 3*5+1);
  hs3.servo = 2;
  hs4 = new HScrollbar(0, 200, width, 10, 3*5+1);
  hs4.servo = 3;
  hs5 = new HScrollbar(0, 250, width, 10, 3*5+1);
  hs5.servo = 4;
  hs6 = new HScrollbar(0, 300, width, 10, 3*5+1);
  hs6.servo = 5;
  
  // init serial port
   port = new Serial(this, portname, 9600);
}

void draw()
{
  background(255);
  
  // Get the position of the top scrollbar
  // and convert to a value to display the top image 
  hs1.update();
  hs2.update();
  hs3.update();
  hs4.update();
  hs5.update();
  hs6.update();
  
  hs1.display();
  hs2.display();
  hs3.display();
  hs4.display();
  hs5.display();
  hs6.display();
  
  if (millis() >= lastSerial + sDelay) { // don't overload the baby
    lastSerial = millis();
    switch(sCount) {
      case 0:
         port.write("s0" + nf((int)hs1.newspos * 10, 4));
         break;
      case 1:
          port.write("s1" + nf((int)hs2.newspos * 10, 4));
         break;
      case 2:
         port.write("s2" + nf((int)hs3.newspos * 10, 4));
         break;
      case 3:
         port.write("s3" + nf((int)hs4.newspos * 10, 4));
         break;
      case 4:
         port.write("s4" + nf((int)hs5.newspos * 10, 4));
         break;
      case 5:
         port.write("s5" + nf((int)hs6.newspos * 10, 4));
         break; 
    }
    sCount++;
    if (sCount == 6) {
      sCount = 0; 
    }    
  }
  // delay(500); // to slow down the update
}


class HScrollbar
{
  int swidth, sheight;    // width and height of bar
  int xpos, ypos;         // x and y position of bar
  float spos, newspos;    // x position of slider
  int sposMin, sposMax;   // max and min values of slider
  int loose;              // how loose/heavy
  boolean over;           // is the mouse over the slider?
  boolean locked;
  float ratio;
  int servo;              // to keep track of servo

  HScrollbar (int xp, int yp, int sw, int sh, int l) {
    swidth = sw;
    sheight = sh;
    int widthtoheight = sw - sh;
    ratio = (float)sw / (float)widthtoheight;
    xpos = xp;
    ypos = yp-sheight/2;
    spos = xpos + swidth/2 - sheight/2;
    newspos = spos;
    sposMin = xpos;
    sposMax = xpos + swidth - sheight;
    loose = l;
    
    PFont fontA = loadFont("Ziggurat-HTF-Black-32.vlw");
    textFont(fontA, 12);

  }

  void update() {
    if(over()) {
      over = true;
    } else {
      over = false;
    }
    if(mousePressed && over) {
      locked = true;
    }
    if(!mousePressed) {
      locked = false;
    }
    if(locked) {
      newspos = constrain(mouseX-sheight/2, sposMin, sposMax);
    }
    if(abs(newspos - spos) > 1) {
      spos = spos + (newspos-spos)/loose;
    }
  }

  int constrain(int val, int minv, int maxv) {
    return min(max(val, minv), maxv);
  }

  boolean over() {
    if(mouseX > xpos && mouseX < xpos+swidth &&
    mouseY > ypos && mouseY < ypos+sheight) {
      return true;
    } else {
      return false;
    }
  }

  void display() {
    fill(255);
    rect(xpos, ypos, swidth, sheight);
    // show bar
    fill(225);

    rect(0, ypos - 1, width, sheight + 2); 

    if(over || locked) {
      fill(153, 102, 0);
    } else {
      fill(102, 102, 102);
    }
    rect(spos, ypos, sheight, sheight);

    // disp value for ref
    text("s" + servo + nf((int)newspos * 10, 4), width/2, ypos - 16);
  }

  float getPos() {
    // Convert spos to be values between
    // 0 and the total width of the scrollbar
    return spos * ratio;
  }
}
